package com.meida.student.app.user.handler.pc;

import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.PayMessage;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.handler.PayInfoHandler;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.GetPayParams;
import com.meida.common.utils.JsonUtils;
import com.meida.module.bus.client.entity.BusOrder;
import com.meida.module.bus.client.enums.OrderTypeEnum;
import com.meida.module.bus.client.enums.PayStateEnum;
import com.meida.module.bus.provider.service.BusOrderAnswerService;
import com.meida.module.bus.provider.service.BusOrderService;
import com.meida.module.marketing.provider.service.CouponUserService;
import com.meida.module.pay.client.entity.PayInfo;
import com.meida.module.pay.provider.handler.PaySuccessHandler;
import com.meida.module.pay.provider.service.PayInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Map;

/**
 * 订单微信支付处理器
 *
 * @author zyf
 */
@Component("pcOrderWeiXinPayHandler")
@Slf4j
public class PcOrderWeiXinPayHandler implements PayInfoHandler, PaySuccessHandler {

    @Autowired
    private PayInfoService payInfoService;

    @Autowired
    private BusOrderService busOrderService;

    @Autowired
    private BusOrderAnswerService busOrderAnswerService;

    @Autowired
    private CouponUserService couponUserService;


    /**
     * 订单回调检验
     *
     * @param payMessage 支付回调消息
     * @param context    上下文参数,可传递到success方法内
     * @param payService 支付服务
     * @param outTradeNo 订单号
     * @return
     */
    @Override
    public boolean validate(PayMessage payMessage, Map<String, Object> context, PayService payService, String outTradeNo) {
        return payInfoService.validate(outTradeNo);
    }


    /**
     * 订单回调业务处理
     *
     * @param payMessage 支付回调消息
     * @param outTradeNo 订单号
     * @param context    上下文参数
     * @param payService 支付服务
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean success(PayMessage payMessage, String outTradeNo, Map<String, Object> context, PayService payService) {
        log.info("支付回调--------------------------" + outTradeNo);
        Map<String, Object> params = payMessage.getPayMessage();
        GetPayParams payParams = new GetPayParams(params);
        if (FlymeUtils.isNotEmpty(payParams)) {
            Long couponUserId = payParams.get("couponUserId");
            Long answerId = payParams.get("answerId");
            BigDecimal payableAmount = payParams.getBigDecimal("payableAmount");
            BigDecimal discountAmount = payParams.getBigDecimal("discountAmount");
            String payType = payMessage.getPayType();
            busOrderService.orderPaySuccess(outTradeNo, payType, couponUserId, answerId, payableAmount, discountAmount);
        } else {
            log.info("支付回调:参数异常", params);
        }
        return payInfoService.success(context, PayStateEnum.HavePay.getValue());
    }

    @Override
    public ResultBody validate(CriteriaSave cs, EntityMap requestMap) {
        String outTradeNo = requestMap.get("outTradeNo");
        Long userId = OpenHelper.getUserId();
        requestMap.put("userId", userId);
        BusOrder busOrder = busOrderService.findByOrderNo(outTradeNo);
        Long orderUserId = busOrder.getUserId();
        if (!orderUserId.equals(userId)) {
            return ResultBody.failed("付款订单用户不符");
        }
        if (FlymeUtils.isEmpty(busOrder)) {
            return ResultBody.failed("订单不存在");
        }
        Integer payState = busOrder.getPayState();
        if (PayStateEnum.HavePay.getValue() == payState) {
            return ResultBody.failed("该订单已支付");
        }
        Integer orderType = busOrder.getOrderType();
//        if (OrderTypeEnum.HomeWork.getValue().equals(orderType)) {
//            Long answerUserId = busOrder.getAnswerUserId();
//            if (FlymeUtils.isEmpty(answerUserId)) {
//                return ResultBody.failed("该订单未完成出价,不能进入支付流程");
//            }
//        }
        return ResultBody.ok();
    }

    @Override
    public void prepare(CriteriaSave criteriaSave, EntityMap entityMap) {
    }

    @Override
    public void complete(CriteriaSave cs, EntityMap requestMap, Object entity) {

    }

    @Override
    public Object getPayInfo(CriteriaSave cs, EntityMap requestMap, String outTradeNo) {
        PayInfo payInfo = cs.getEntity(PayInfo.class);
        Long couponUserId = requestMap.getLong("couponUserId");
        Long answerId = requestMap.getLong("answerId");
        Long payId = requestMap.getLong("payId");
        BusOrder busOrder = busOrderService.findByOrderNo(outTradeNo);
        ApiAssert.isNotEmpty("订单不存在", busOrder);
        BigDecimal orderAmount = busOrder.getOrderAmount();
        BigDecimal payableAmount = busOrder.getPayableAmount();
        //支付时重新计算折扣金额
        BigDecimal discountAmount = couponUserService.calculateDiscountAmountByCouponUserId(couponUserId, orderAmount);
        if (FlymeUtils.gtzero(discountAmount)) {
            payableAmount = payableAmount.subtract(discountAmount);
        }
        Integer orderType = busOrder.getOrderType();
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.getByValue(orderType);
        payInfo.setOrderTitle(orderTypeEnum.getLabel());
        payInfo.setOrderEntity(BusOrder.class.getSimpleName());
        payInfo.setOrderBody(orderTypeEnum.getLabel() + "订单支付");
        payInfo.setBusId(busOrder.getOrderId());
        payInfo.setOrderEntity(BusOrder.class.getSimpleName());
        payInfo.setOrderAmount(payableAmount);
        EntityMap attach = new EntityMap();
        attach.put("couponUserId", couponUserId);
        attach.put("answerId", answerId);
        attach.put("payableAmount", payableAmount);
        attach.put("discountAmount", discountAmount);
        attach.put("payId", payId);
        payInfo.setAttach(JsonUtils.beanToJson(attach));
        payInfo.setOrderImage(busOrder.getCoverImg());
        return payInfo;
    }
}
